package maMetrics;

import java.util.Iterator;

import maConfigration.MetricSettings;
import maUtil.LogFile;
import maUtil.RecordUnit;
import maUtil.SortedRecords;

import com.telelogic.rhapsody.core.IRPAttribute;
import com.telelogic.rhapsody.core.IRPClass;
import com.telelogic.rhapsody.core.IRPEvent;
import com.telelogic.rhapsody.core.IRPInterfaceItem;
import com.telelogic.rhapsody.core.IRPOperation;
import com.telelogic.rhapsody.core.IRPPackage;
import com.telelogic.rhapsody.core.IRPProject;
import com.telelogic.rhapsody.core.IRPState;
import com.telelogic.rhapsody.core.IRPStatechart;
import com.telelogic.rhapsody.core.IRPTransition;

public class MetricsSizeOfStatechart extends MetricObject {

	
	protected int _nListLength = 20;
	
	SortedRecords _srStatesProj = null;
	SortedRecords _srTransProj = null;
	SortedRecords _srEventsProj = null;
	
	LogFile _logSC = null;
	LogFile _logProjList = null;
	LogFile _logRawData = null;
	
	protected int _nStateSum = 0;
	protected int _nTransSum = 0;
	protected int _nEventSum = 0;


	public MetricsSizeOfStatechart(MetricSettings ms)
	{
		super(ms);
		_sMetricName = "Metric: Size Of Statechart";
		
		_logSC = new LogFile("MetricSizeOfSCLog.txt");
		_logProjList = new LogFile("MetricSizeOfSCLogProjTop.txt");

		if(_isLogRawData)
		{
			_logRawData = new LogFile("MetricSOSRawData.csv");
			_logRawData.logLn("Value,Classname");
		}
		
		_nListLength = 20;
		
		_srStatesProj = new SortedRecords(_nListLength, null);
		_srTransProj = new SortedRecords(_nListLength, null);
		_srEventsProj = new SortedRecords(_nListLength, null);
		
	}


	@Override
	public int applyInProj(IRPProject proj) {
		// TODO Auto-generated method stub
		if(proj == null) return 0;
		if(_srStatesProj.getSize() > 0)
		{				
			if(_srStatesProj.getName()==null) 
				_srStatesProj.setName(_sMetricName + ":Top " + 
					_nListLength + " class with hight states number in statechat from project " + proj.getName());
			_logProjList.log(_srStatesProj.getAllString());
		}
		_srStatesProj = new SortedRecords(_nListLength, null);
		
		if(_srTransProj.getSize() > 0)
		{				
			if(_srTransProj.getName()==null) 
				_srTransProj.setName(_sMetricName + ":Top " + 
					_nListLength + " class with hight Transition number in statechat from project " + proj.getName());
			_logProjList.log(_srTransProj.getAllString());
		}
		_srTransProj = new SortedRecords(_nListLength, null);
		
		if(_srEventsProj.getSize() > 0)
		{				
			if(_srEventsProj.getName()==null) 
				_srEventsProj.setName(_sMetricName + ":Top " + 
					_nListLength + " class with hight event number in statechat from project " + proj.getName());
			_logProjList.log(_srEventsProj.getAllString());
		}
		_srEventsProj = new SortedRecords(_nListLength, null);
		
		int n = _nTransSum + _nStateSum + _nEventSum;
		_nStateSum = 0;
		_nTransSum = 0;
		_nEventSum = 0;
		return n;
	}

	@Override
	public int applyInPkg(IRPPackage pkg) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public int applyInCls(IRPClass cls) {
		// TODO Auto-generated method stub
		int[] ret = countStatechart(cls);
		if(ret == null || ret.length < 3)
			return 0;
		if(_isApplyToProj)
		{
			if(ret[0] > 0 && (_srStatesProj.notFull() || ret[0] > _srStatesProj.getMinValue()))
			{
				RecordUnit ru = new RecordUnit(ret[0], cls.getFullPathNameIn());
				if(_srStatesProj.notFull())
					_srStatesProj.addWithoutSort(ru);
				else
					_srStatesProj.add(ru);
			}
			if(ret[1] > 0 && (_srTransProj.notFull() || ret[1] > _srTransProj.getMinValue()))
			{
				RecordUnit ru = new RecordUnit(ret[1], cls.getFullPathNameIn());
				if(_srTransProj.notFull())
					_srTransProj.addWithoutSort(ru);
				else
					_srTransProj.add(ru);
			}
			if(ret[2] > 0 && (_srEventsProj.notFull() || ret[1] > _srEventsProj.getMinValue()))
			{
				RecordUnit ru = new RecordUnit(ret[1], cls.getFullPathNameIn());
				if(_srEventsProj.notFull())
					_srEventsProj.addWithoutSort(ru);
				else
					_srEventsProj.add(ru);
			}
		}
		String str = cls.getFullPathNameIn() + " has: \r\n" + ret[0] + "\t" + "states\r\n"
				+ ret[1] + "\t" + "transitions\r\n" + ret[2] + "\t" + "events\r\n\r\n";
		_logSC.log(str);
		
		_nStateSum += ret[0];
		_nTransSum += ret[1];
		_nEventSum += ret[2];
		
		int n = ret[0] + ret[1] + ret[2];
		
		if(_isLogRawData && n>0) 
			_logRawData.logLn(n + "," + cls.getFullPathNameIn());
			
		return n;
	}

	@Override
	public int applyInItf(IRPInterfaceItem itf) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public int applyInOp(IRPOperation op) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public int applyInAttr(IRPAttribute attrb) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public void finish() {
		// TODO Auto-generated method stub
		
	}
	/**
	 * ret[0] number of states in a statechart 
	 * ret[1] number of transitions in a statechart 
	 * ret[2] number of events in a statechart 
	 * **/
	private static int[] countStatechart(IRPClass cls) 
	{
		if(cls == null) return null;
		int nState = 0, nTransition = 0, nEvent = 0;
		IRPStatechart statechart = cls.getStatechart();
		Iterator elementsList = null;
		try{
			elementsList = statechart.getElementsInDiagram().toList().iterator();
		}
		catch(Exception e)
		{
			return null;
		}

		//logSC("Counting element in statechart in class: " + cls.getName() + " package: " +_pkgName);
		while(elementsList != null && elementsList.hasNext())
		{
			Object element = elementsList.next();
			if(element instanceof IRPTransition)
			{
				nTransition ++;
			}
			else if(element instanceof IRPState)
			{
				nState ++;
			}
			else if(element instanceof IRPEvent)
			{
				nEvent ++;
			}
		}
		int[] ret = {nState, nTransition, nEvent};
		return ret;
		
	}


}
